HLP CAPITAL ADVISORY · ENGINEERING

Backend architecture.

Cloudflare D1 schema · Worker API · PDF Report™ generation pipeline · email delivery. Everything the diagnostic suite needs to move from client-side prototypes into production.

D1 SCHEMA
WORKER API
PDF ENGINE
EMAIL DELIVERY
◉ 01 · SYSTEM OVERVIEW

The full flow.

All 8 diagnostics (WIA, PBR, ICR, TSR, EPR, ExR, FOR, MAR) are currently client-side prototypes using localStorage for state persistence. Production requires server-side submission, storage, PDF generation, and email delivery — plus admin views for Chekelah's team.

┌─ CLIENT ─────────────────────────┐ │ Voice-enabled diagnostic form │ │ localStorage state (autosave) │ └──────────┬───────────────────────┘ │ POST /api/submit ▼ ┌─ CLOUDFLARE WORKER (API) ────────┐ │ Validate + Turnstile check │ │ Insert into D1 │ │ Queue PDF job │ └──────────┬───────────────────────┘ │ ├──▶ D1 DATABASE │ submissions │ scores │ routing │ ├──▶ QUEUE (Cloudflare Queues) │ pdf.generate │ email.send │ └──▶ R2 (Object Storage) reports/{id}.pdf
◉ 02 · D1 SCHEMA

The data model.

Table: submissions

Master table for every diagnostic submission across all 8 report types.

CREATE TABLE submissions (
  id              TEXT PRIMARY KEY,           -- UUID v7
  diagnostic      TEXT NOT NULL,             -- WIA | PBR | ICR | TSR | EPR | ExR | FOR | MAR | BOD
  version         TEXT NOT NULL,             -- v1
  submitted_at    INTEGER NOT NULL,          -- unix ms
  applicant_name  TEXT,
  applicant_email TEXT NOT NULL,
  applicant_phone TEXT,
  applicant_company TEXT,
  consent_terms   INTEGER NOT NULL,          -- 1 = accepted
  raw_state       TEXT NOT NULL,             -- JSON of all form answers
  ip_hash         TEXT,                      -- SHA-256 (privacy-preserving)
  user_agent      TEXT,
  turnstile_score REAL,
  utm_source      TEXT,
  utm_campaign    TEXT,
  status          TEXT NOT NULL DEFAULT 'submitted'  -- submitted | pdf-generated | delivered | reviewed | routed
);

CREATE INDEX idx_sub_email ON submissions(applicant_email);
CREATE INDEX idx_sub_diagnostic ON submissions(diagnostic, submitted_at DESC);
CREATE INDEX idx_sub_status ON submissions(status);

Table: scores

Computed scores for each submission — derived from raw_state at submission time, cached for admin queries.

CREATE TABLE scores (
  submission_id   TEXT PRIMARY KEY REFERENCES submissions(id),
  overall_score   INTEGER NOT NULL,          -- 0-100
  tier_band       TEXT NOT NULL,             -- e.g. "TIER 03 · COORDINATION-READY"
  tier_verdict    TEXT NOT NULL,
  top_moves       TEXT NOT NULL,             -- JSON array of 6-12 moves with per-move scores
  computed_at     INTEGER NOT NULL
);

Table: routing

Specialist-routing recommendations produced by the diagnostic — used to trigger partner-firm handoffs.

CREATE TABLE routing (
  id              TEXT PRIMARY KEY,
  submission_id   TEXT NOT NULL REFERENCES submissions(id),
  specialist_type TEXT NOT NULL,             -- CPA | ATTORNEY | LENDER | IB | INSURANCE | RIA
  discipline      TEXT NOT NULL,             -- ESTATE, M&A, TAX-PLANNING, SBA, JUMBO, etc.
  urgency         TEXT NOT NULL,             -- URGENT | HIGH | STANDARD
  partner_id      TEXT REFERENCES partners(id), -- nullable · matched later
  status          TEXT NOT NULL DEFAULT 'unmatched', -- unmatched | matched | intro-sent | engaged | closed
  created_at      INTEGER NOT NULL
);

Table: partners

Vetted partner firms (from Partnership Program) — matched to routing entries.

CREATE TABLE partners (
  id              TEXT PRIMARY KEY,
  firm_name       TEXT NOT NULL,
  primary_contact TEXT NOT NULL,
  email           TEXT NOT NULL,
  specialist_type TEXT NOT NULL,
  disciplines     TEXT NOT NULL,             -- JSON array
  geography       TEXT NOT NULL,             -- e.g. "DFW", "NATIONAL"
  mou_signed_at   INTEGER,
  status          TEXT NOT NULL DEFAULT 'active' -- active | paused | ended
);

Table: reports

Generated PDF reports — R2 object references.

CREATE TABLE reports (
  submission_id   TEXT PRIMARY KEY REFERENCES submissions(id),
  r2_key          TEXT NOT NULL,             -- "reports/{id}.pdf"
  pdf_size_bytes  INTEGER NOT NULL,
  generated_at    INTEGER NOT NULL,
  delivered_at    INTEGER,
  version         TEXT NOT NULL              -- template version
);
◉ 03 · WORKER API

The endpoints.

POST /api/submit

Accepts a diagnostic form submission from the client. Validates, stores, scores, and queues downstream jobs.

// Request body
{
  "diagnostic": "WIA" | "PBR" | "ICR" | "TSR" | "EPR" | "ExR" | "FOR" | "MAR" | "BOD",
  "version": "v1",
  "applicant": {
    "name": "...",
    "email": "...",
    "phone": "...",
    "company": "..."
  },
  "state": { /* full form state, as stored in localStorage */ },
  "turnstile": "...",             // Cloudflare Turnstile CAPTCHA token
  "consent": true
}

// Response
{
  "ok": true,
  "submission_id": "uuid-v7",
  "score": 74,
  "tier_band": "TIER 03 · COORDINATION-READY",
  "report_eta": "2025-11-15T10:00:00Z"
}

GET /admin/queue

Admin-authenticated endpoint (Cloudflare Access-gated) for Chekelah's team to review incoming submissions.

{
  "total_pending_review": 12,
  "submissions": [
    {
      "id": "...",
      "diagnostic": "ICR",
      "applicant": { "name": "...", "email": "...", "company": "..." },
      "score": 74,
      "tier_band": "...",
      "submitted_at": 1730000000000,
      "pdf_url": "https://reports.hlpcredit.com/...",
      "routing_recommendations": [ /* array of specialist recs */ ]
    }
  ]
}

POST /admin/route/:submission_id

Chekelah's team matches routing entries to specific partner firms + sends warm-intro emails.

Auth. All /admin/* endpoints are gated by Cloudflare Access with Google Workspace SSO limited to @hlpcredit.com domain. No auth token leaks — Cloudflare handles session management.
◉ 04 · PDF ENGINE

The Report™ generator.

PDF generation runs as a queued job — decoupled from the submit response to keep the client-side experience snappy.

Pipeline

1. QUEUE MESSAGE { submission_id, diagnostic, version } 2. TEMPLATE FETCH R2: templates/{diagnostic}/v1/template.html Server-side Handlebars rendering with score data 3. HTML → PDF Cloudflare Browser Rendering API (or fallback: puppeteer via containers) 4. STORAGE R2: reports/{submission_id}.pdf INSERT INTO reports table 5. TRIGGER EMAIL Queue: email.deliver Template: report-delivery.mjml

Templates

Every diagnostic has its own PDF template stored in R2. Templates use Handlebars for dynamic score data + move rendering:

templates/
├── WIA/v1/
│   ├── template.html          // Handlebars HTML
│   ├── styles.css             // Print-optimized CSS
│   └── cover.svg
├── PBR/v1/
├── ICR/v1/
├── TSR/v1/
├── EPR/v1/
├── ExR/v1/
├── FOR/v1/
├── MAR/v1/
└── shared/
    ├── header.html            // HLP logo + report meta
    ├── footer.html            // Compliance disclaimer
    └── styles-base.css
Signed URLs. Generated PDFs are stored in R2 with 30-day signed URLs. Chekelah's team + the client each receive the same URL. Not public — requires the signed token.
◉ 05 · EMAIL DELIVERY

The 48-hour promise.

Every diagnostic promises delivery within 48 hours. Two-stage email flow ensures both machine-speed acknowledgment and human-review completion.

StageTriggerTemplateContents
01 · IMMEDIATEOn submissionsubmission-receivedConfirmation · score preview · 48hr Report™ promise
02 · PDF READYPDF generated (queue)report-previewPDF Report™ · signed URL · Chekelah review note
03 · CHEKELAHManual · Chekelahpersonal-followupPersonal note · specialist introductions · book-a-call CTA

Email is sent via Cloudflare Email Routing for inbound and Resend for outbound transactional. MJML templates render to responsive HTML.

Voice recordings. Voice-enabled fields transmit the transcribed text — never the audio itself. No audio data leaves the browser. Zero HIPAA / GLBA voice-recording exposure.
◉ 06 · COMPLIANCE + SECURITY

The guardrails.

ControlImplementation
PII AT RESTD1 stores raw form state · Cloudflare-native encryption at rest
PII IN TRANSITTLS 1.3 everywhere · HSTS · CSP headers on client
IP HASHINGClient IP SHA-256 hashed before storage · never raw
DATA RETENTIONSubmissions purged after 24 months · reports after 12 months
ACCESS CONTROLCloudflare Access · SSO-gated · @hlpcredit.com domain only
AUDIT LOGAll admin actions written to append-only D1 audit_log table
DATA EXPORTClients can request full data export via GLBA/CCPA endpoint
DATA DELETION60-day full-deletion SLA on client request
THIRD-PARTYZero third-party analytics · zero ad trackers · zero session replay
◉ 07 · DEPLOYMENT · CLOUDFLARE PAGES

Where it lives.

Following the existing HLP subdomain architecture:

ComponentCloudflare ProductURL
Client (static)Pagescapital.hlpcredit.com
API WorkerWorkersapi.hlpcredit.com
DatabaseD1hlp-capital-advisory (binding)
Object storageR2hlp-reports (bucket)
QueueCloudflare Queueshlp-pdf, hlp-email
Admin consolePages + Accessadmin.hlpcredit.com
PDF viewerPages · signed URLreports.hlpcredit.com
Total monthly cost estimate. At 500 submissions/month: Cloudflare Workers < $10 · D1 < $5 · R2 < $15 · Resend email < $20 · Cloudflare Access free tier. Total: under $60/month at forecast Year-1 volume.
◉ 08 · IMPLEMENTATION ROADMAP

The build order.

Recommended 4-phase implementation:

  1. Phase 1 · Week 1-2: D1 schema · Worker /api/submit · basic PDF generation (single template) · admin queue view
  2. Phase 2 · Week 3-4: All 8 report PDF templates · email delivery pipeline · signed URLs · Turnstile CAPTCHA
  3. Phase 3 · Week 5-6: Admin routing UI · partner-matching workflow · warm-intro email automation
  4. Phase 4 · Week 7-8: Analytics dashboard · GLBA/CCPA export endpoints · retention automation · MFA hardening